package org.btallarm.gui;

import org.btallarm.math.Filter;
import org.btallarm.model.Angle;
import org.btallarm.model.Note;
import org.btallarm.model.State;
import org.btallarm.model.Threshold;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;

public class CustomView extends View implements SensorEventListener {
	public TextView txtX,txtY,txtZ; 
	
	// State
	private State state=null;
	private Threshold threshold=null;
	private org.btallarm.model.Note note=null;
	
	
	// Variables for sensor computation
	private float[] mags = null;
	private float[] accels = null;
	private float[] R = new float[9];
	private float[] outR = new float[9];
	private float[] I = new float[9];
	private float[] values = new float[3];
	private float x,y,z;
	private Filter xFilter, yFilter, zFilter;
    
	// Variables for sensor draw
    private Bitmap  mBitmap;
    private Paint   mPaint = new Paint();
    private Canvas  mCanvas = new Canvas();
    private Path    mPath = new Path();
    private RectF   mRect = new RectF();
    private float   mLastValues[] = new float[3*2];
    private float   mOrientationValues[] = new float[3];
    private int     mColors[] = new int[3*2];
    private float   mLastX;
    private float   mScale[] = new float[2];
    private float   mYOffset;
    private float   mMaxX;
    private float   mSpeed = 1.0f;
    private int mWidth, mHeight; 
    
    
    
    
	public CustomView(Context context,AttributeSet attrs){
		super(context,attrs);
		mColors[0] = Color.argb(192, 255, 64, 64);
        mColors[1] = Color.argb(192, 64, 128, 64);
        mColors[2] = Color.argb(192, 64, 64, 255);
        mColors[3] = Color.argb(192, 64, 255, 255);
        mColors[4] = Color.argb(192, 128, 64, 128);
        mColors[5] = Color.argb(192, 255, 255, 64);

        mPaint.setFlags(Paint.ANTI_ALIAS_FLAG);
        mRect.set(-0.5f, -0.5f, 0.5f, 0.5f);
        mPath.arcTo(mRect, 0, 180);
        
        txtX = new TextView(context);
        txtX.setTextColor(Color.WHITE);
        txtX.setText("test"); 
        
        xFilter = new Filter();
        yFilter = new Filter();
        zFilter = new Filter();
        
        state= new State();
	}
	 @Override
     protected void onDraw(Canvas canvas) {
		 super.onDraw(canvas);
		 
			mWidth =this.getWidth();
	        mHeight=this.getHeight();
	        mBitmap = Bitmap.createBitmap(mWidth,mHeight, Bitmap.Config.RGB_565);
	        mCanvas.setBitmap(mBitmap);
	        mCanvas.drawColor(0x00000000);
	        mYOffset = mHeight * 0.5f;
	        mScale[0] = - (mHeight * 0.5f * (1.0f / (SensorManager.STANDARD_GRAVITY * 2)));
	        mScale[1] = - (mHeight * 0.5f * (1.0f / (SensorManager.MAGNETIC_FIELD_EARTH_MAX)));
	        mMaxX = mWidth;
	        mLastX = mMaxX;
		       
		     synchronized (this) {
             if (mBitmap != null) {
                 final Paint paint = mPaint;
                 final Path path = mPath;
                 final int outer = 0xFFC0C0C0;
                 final int inner = 0xFFff7010;

                 canvas.drawBitmap(mBitmap, 0, 0, null);
                 
                 float[] values = mOrientationValues;
                 
                 float w0 = mWidth * 0.333333f;
                 float w  = w0 - 32;
                 float x = w0*0.5f;
                 for (int i=0 ; i<3 ; i++) {
                     canvas.save(Canvas.MATRIX_SAVE_FLAG);
                     canvas.translate(x, w*0.5f + 4.0f);
                     canvas.save(Canvas.MATRIX_SAVE_FLAG);
                     paint.setColor(outer);
                     canvas.scale(w, w);
                     canvas.drawOval(mRect, paint);
                     canvas.restore();
                     canvas.scale(w-5, w-5);
                     paint.setColor(inner);
                     canvas.rotate(-values[i]);
                     canvas.drawPath(path, paint);
                     canvas.restore();
                     x += w0;
                 }
             }
		     }

	         final Paint paint = mPaint;
	         paint.setColor(Color.WHITE); 
	         paint.setTextSize(40); 
	         canvas.drawText("X: "+x, 0, mHeight/2, paint);
	         canvas.drawText("Y: "+y, mWidth * 1 / 3, mHeight/2, paint);
	         canvas.drawText("Z: "+z, mWidth * 2 / 3, mHeight/2, paint);
             
     }

	 public void onSensorChanged(SensorEvent event){
		 //draw_text();
		 
		 onSensorChanged_draw(event);
		 onSensorChanged_calculate(event);
		 
			 
	 }
	 private void onSensorChanged_calculate(SensorEvent event){
		/*if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
	        return;
	    }*/

	    switch (event.sensor.getType()) {
	    case Sensor.TYPE_MAGNETIC_FIELD:
	        mags = event.values.clone();
	        break;
	    case Sensor.TYPE_ACCELEROMETER:
	        accels = event.values.clone();
	        break;
	    }

	    if (mags == null || accels == null) return;
	    
	        SensorManager.getRotationMatrix(R, I, accels, mags);
	        // Correct if screen is in Landscape
	        SensorManager.remapCoordinateSystem(R, SensorManager.AXIS_X, SensorManager.AXIS_Z, outR);
	        SensorManager.getOrientation(outR, values);
	        
	        x=values[0];
	        y=values[1];
	        z=values[2];
	        
	        // Set the filters
	        x = (float) xFilter.doFilt( x );
	        y = (float) yFilter.doFilt( y );
	        z = (float) zFilter.doFilt( z );
	        
	        
	        // Convert the values in degree
	        x = (float) Math.round((Math.toDegrees(x))*7)/7;
	        x = Math.round(( x + 360)%360);
	        y=-Math.round((float) (y*(360/(2*Math.PI))));
	        z=Math.round((float) (z*(360/(2*Math.PI))));

	        // Check if the angle values over the threshold
	        Angle angle=new Angle();
	        angle.setX( new Double(x));
	        angle.setY( new Double(y));
	        angle.setZ( new Double(z));
	        
			 if ( (threshold.getAngle().getX() > x || threshold.getAngle().getX() < -x) ||
			    (threshold.getAngle().getY() > y || threshold.getAngle().getY() < -y)){
				 state.add(angle);
			 }
			 
			 
	}
	 
	 private void onSensorChanged_draw(SensorEvent event){     	
    	 	synchronized (this) {
             if (mBitmap != null) {
                 //final Canvas canvas = mCanvas;
                 //final Paint paint = mPaint;
                 if (event.sensor.getType() == Sensor.TYPE_ORIENTATION) {
                     for (int i=0 ; i<3 ; i++) {
                         mOrientationValues[i] = event.values[i];
                     }
                 } else {
                     float deltaX = mSpeed;
                     float newX = mLastX + deltaX;

                     int j = (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) ? 1 : 0;
                     for (int i=0 ; i<3 ; i++) {
                         int k = i+j*3;
                         final float v = mYOffset + event.values[i] * mScale[j];
                         //paint.setColor(mColors[k]);
                         //canvas.drawLine(mLastX, mLastValues[k], newX, v, paint);
                         mLastValues[k] = v;
                     }
                     if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
                         mLastX += mSpeed;
                 }
                 invalidate();
             }
         }
     }

     public void onAccuracyChanged(Sensor sensor, int accuracy) {
     }
     public State getState (){
    	return this.state; 
     }
     public void setState (State state){
     	this.state=state; 
     }
     public Threshold getThreshold (){
     	return this.threshold; 
      }
      public void setThreshold (Threshold threshold){
      	this.threshold=threshold; 
      }
      public Note getNote(){
      	return this.note; 
       }
       public void setNote (Note note){
       	this.note=note; 
       }
}
